package org.NooLab.glue.recdispatcher;

import java.util.Arrays;
import java.util.Vector;

import org.NooLab.glue.MessageBoard;
import org.NooLab.glue.filter.MessageInterpreter;
import org.NooLab.glue.msgframe.BasicMessageParams;
import org.NooLab.glue.msgframe.XMessage;
import org.NooLab.glue.msgframe.XRegistration;
import org.NooLab.glue.transaction.Transaction;
import org.NooLab.glue.transaction.Transactions;
import org.NooLab.utilities.logging.PrintLog;
import org.NooLab.utilities.strings.StringsUtil;



public class ControlTaskHandler 
									extends 
												MessageInterpreter 
									implements 
												Runnable{

	MessageBoard mb;
	
	XRegistration xreg;
	Transactions transactions;
	
	Vector<String> acceptedTaskUID = new Vector<String>();
	
	String rawXmlMsg;
	String taskLabel;
	long instanceID;
	
 
	XMessage xmsg;
	
	Thread cthThrd;
	PrintLog out;
	StringsUtil strgutil = new StringsUtil() ;
	
	
	public ControlTaskHandler( 	MessageBoard msgboard, String originatorID, long instanceID,
								String taskLabel, String parameters,String rawXmlMsg, PrintLog outprn) {
		
		super( msgboard, null, outprn );
		
		mb = msgboard;
		xreg = mb.retrieveRegistrationObject( instanceID ) ; 
		
		this.instanceID = instanceID;
		this.rawXmlMsg = rawXmlMsg;
		this.taskLabel = taskLabel;
	
		transactions = mb.getTransactions() ;
		
		cthThrd = new Thread(this,"mb-ControlTaskHandler-"+instanceID); 
		out = outprn;
		
	}
	
	public void go(){
		
		cthThrd.start();
	}
	
	private void dispatchingTask(){
		
		String privateSecret;
		
		
		xmsg = new XMessage(out);
		
		// blocking repeated sends by random UUID
		
		privateSecret = xmsg.getSpecifiedInfo(rawXmlMsg, "control", "secret") ;
		
		if (acceptedTaskUID.indexOf(privateSecret)<0){
			acceptedTaskUID.add( privateSecret );
		} else{
			return;
		}
		// we keep just the last 100 messages (count of repeats is usually <5)
		if (acceptedTaskUID.size()>100){
			acceptedTaskUID.remove(0) ;
		}
		
		// ..............................
		
		if (taskLabel.toLowerCase().contentEquals("cancel")){
			cancelTransactions();
		}
		
		
		
		
	}

	public void run() {
		 
		dispatchingTask();
	}
	
	// ....................................................
	
	/**
	 * 
	 * ultimately triggered by sourceControl_CancelReceptorTaskbyTransactionID(),
	 * which then creates this instance of the ControlTaskHandler
	 * 
	 */
	private void cancelTransactions(){
		String paramStr, listedIDs="",str,secret,subject="",  xmlout ="", notTreatedRqTids="";
		long tid, iid,deltid;
		int del=0,mode=-1,ix,r;
		Transaction transaction;
		boolean hb;
		Long[] paramtids = new Long[0];
		
		try{
		/*
			
<messageboard name="spela" role="SOURCE">
   <transaction>
      <control secret="6ea012ae-bdc2-45c0-b134-970fe6bd36a9"/>
      <transaction id="-9"/>
      <instance id="2528" name="testSource0-source-1-4a3871c9-f687-40b4-8d2d-53ec78b5f00b"/>
      <task param="all" type="cancel"/>
   </transaction>
<originator id="BaseResource$MessageSupply@1370ce9"/>
</messageboard>

		*/
												out.print(3, "cancelTransactions()") ;
												out.print(4,rawXmlMsg);

			// is present only for http, for tcp+ it does not play any role 							
			originatorID = xmsg.getSpecifiedInfo(rawXmlMsg, "//originator", "id");
			
			tid = xmsg.getSpecifiedValue(rawXmlMsg, "transaction", "id");
			
			if (tid!=-9){ 
				return; // i.e.: no confirmation
			}

			secret = xmsg.getSpecifiedInfo(rawXmlMsg, "control", "secret");

			paramStr = xmsg.getSpecifiedInfo(rawXmlMsg, "task", "param") ;
			
			// <task param="all" type="cancel"/>
			if (paramStr.toLowerCase().contains("all")){
				mode=9;
				subject = "cancel-all";  
				notTreatedRqTids = "all" ;
			}
			//  a list of int or a single int?  
			if ( (paramStr.contains(";")) || (strgutil.isNumericX( paramStr))){
				mode=1;
				
				String[] paramtidsStr = paramStr.split(";");
				paramtids = new Long[paramtidsStr.length];
				for (int i=0;i<paramtidsStr.length;i++){
					str = paramtidsStr[i];
					paramtids[i]= -1L;
					if (strgutil.isNumericX(str)){
						paramtids[i] = Long.parseLong(str) ;
					}
				}
				notTreatedRqTids = paramStr+";";
				subject = "cancel";
			}
			if (mode<0){
				return;
			}
			
			
			BasicMessageParams basics = new BasicMessageParams();
			basics.transactionID = -9 ;
			basics.instanceID = instanceID;
			basics.privateTransactionIdentifier = secret;
			basics.roleOfSender = "BOARD" ;
			
			
			Arrays.sort(paramtids); // needed for painless detection of a tid in the array
			//
			
			// <confirmation secret="testSource0-source-1-4a3871c9-f687-40b4-8d2d-53ec78b5f00b" type="task::cancel-all"
			
			for (int i=0;i<transactions.size();i++){
				transaction = transactions.getItem(i) ;
				
				iid = transaction.getInstanceID();
				tid = transaction.getTransactionID() ;
				
				if (iid == instanceID){
					 
					if (mode==9){
						hb=true;
					}else{
						ix = Arrays.binarySearch( paramtids, tid);
						hb = (ix>=0) ;
					}
					
					if (hb){
						transaction.setTransactState( Transaction.TS_TASK_CANCELED);
						deltid = transaction.getTransactionID();
						del++;
						if (listedIDs.length()>0){ listedIDs=listedIDs+";";}
						listedIDs = listedIDs+tid;
						notTreatedRqTids = notTreatedRqTids.replace( ""+tid+";", "");
					}else{
						// simply: we do not remove it from the list of non-treated tid!
						// so the client can deal with it...
						
					}
				} // instanceID ?
			}
			transactions.save();
			
			if (del>0){
				str = "s have";
				if (del==1){str=" has";};
				out.printErr(2, "\n"+del+" transaction"+str+" been cancelled upon request received from instance id="+instanceID);
				
			}else{
				out.print(2, "instance id="+instanceID+" requested cancellation of all its transactions, but there have not been any.");
			}
			
			// see also:  xmsg.createConfirmationAboutDelivery();
			xmlout = xmsg.createCancellationConfirmation( basics, subject, listedIDs, notTreatedRqTids );
			
			 
			// http: originator, prolog
			
			// <param value="1;2;3;4;5" unknown="6;7"> 
			
			r = wrappedSending( xmsg, xreg, xmlout , "data", "post",0) ; // rawXmlMsg
				
		}catch(Exception e){
			
		}
	}

	 
	


}
